<script lang="ts" setup>
import * as Y from "yjs";
import { WebsocketProvider } from "y-websocket";
import { MonacoBinding } from "y-monaco";
import * as monaco from "monaco-editor";
import * as awarenessProtocol from "y-protocols/awareness.js";

const roomName = "monaco-demo";
const textValue = ref<string>("");

const ydoc = new Y.Doc();
const awareness = new awarenessProtocol.Awareness(ydoc);

const ytext = ydoc.getText("monaco");
const provider = new WebsocketProvider(
  "ws://localhost:6234", // use the public ws server
  // `ws${location.protocol.slice(4)}//${location.host}/ws`, // alternatively: use the local ws server (run `npm start` in root directory)
  roomName, // room name
  ydoc,
);
type StatusType = "disconnected" | "connecting" | "connected";

// another button
const connectBtnText = ref<StatusType>("disconnected");
const connectBtnColor = computed(() => {
  return connectBtnText.value === "connected" ? "green" : "red";
});
const theMonacoEditor = ref<HTMLElement>();

provider.on("status", (event: { status: StatusType }) => {
  connectBtnText.value = event.status; // logs "connected" or "disconnected"
});

onMounted(() => {
  nextTick(() => {
    if (!theMonacoEditor.value) {
      console.error("No monaco editor found");
      return;
    }

    // set src
    const editor = monaco.editor.create(theMonacoEditor.value, {
      value: textValue.value,
      language: "typescript",
      theme: "vs-dark",
    });
    const monacoBinding = new MonacoBinding(
      ytext,
      editor.getModel()!,
      new Set([editor]),
      awareness,
    );
      // @ts-expect-error to window
    window.example = { provider, ydoc, ytext, monacoBinding };
  },
  )
});

const handleConnect = () => {
  if (provider.shouldConnect) {
    provider.disconnect();
    connectBtnText.value = "connected";
  }
  else {
    provider.connect();
    connectBtnText.value = "disconnected";
  }
};
onBeforeUnmount(() => {
  console.log("unmounting y-comp.vue");
  provider.disconnect();
  provider.destroy();
});
</script>

<template>
  <div>
    <ClientOnly>
      <div class="p-2 *:m-2">
        <UButton :color="connectBtnColor" @click="handleConnect">
          {{ connectBtnText }}
        </UButton>
      </div>
      <div class="h-[500px] w-full">
        <div ref="theMonacoEditor" class="h-full w-full" />
      </div>
      <template #fallback>
        <p>Loading comments...</p>
      </template>
    </ClientOnly>
  </div>
</template>

<style scoped>
.yRemoteSelection {
  background-color: rgb(250, 129, 0, 0.5);
}
.yRemoteSelectionHead {
  position: absolute;
  border-left: orange solid 2px;
  border-top: orange solid 2px;
  border-bottom: orange solid 2px;
  height: 100%;
  box-sizing: border-box;
}
.yRemoteSelectionHead::after {
  position: absolute;
  content: " ";
  border: 3px solid orange;
  border-radius: 4px;
  left: -4px;
  top: -5px;
}
</style>
